# @Time : 2020/7/28 15:27
# @Author : Fioman 
# @Phone : 13149920693
import cv2 as cv
import numpy as np

"""
一个轮廓对应着一系列的点,这些点以某种方式表示图像中的一条曲线.
在opencv中,函数cv.findContours()用于查找图像的轮廓,并能够根据参数返回特定表示方式的轮廓(曲线).
函数cv.drawContours()能够将查找的轮廓绘制到图像上,该函数可以根据参数再图像上绘制不同的样式.
image,contours,hierarchy = cv.findContours(image,mode,method)
返回值:
image与参数的image一致.
contours: 返回的轮廓
hierarchy: 图像的拓扑信息(轮廓层次)
mode: 轮廓的检索模式
method: 轮廓的近似方法.
参数mode决定了轮廓的提取方式,具体有如下4种:
cv.RETR_EXTERNAL  只检测外轮廓
cv.RETR_LIST  对检测到的轮廓不建立等级关系
cv.RETR_CCOMP 检索所有的轮廓,并将它们组织成两级层次结构.
上面的一层为外边界,下面的一层为内控的边界.如果内孔内还有一个连通物体,
那么这个物体的边界仍然位于顶层.

cv.TRTR_TREE: 建立一个等级树结构的轮廓.
method -> 
cv.CHAIN_APPROX_NONE:
存储所有的轮廓点,相邻两个点的像素位置差不超过1.即max(abs(x1-x2),bas(y2-y1)) = 1.

cv.CHAIN_APPROX_SIMPLE:
压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标.例如,极端情况下,一个矩形只需要用4个点来保存轮廓信息.

cv.findContours() 查找轮廓的时候需要注意一下几点:
1> 待处理的源图像必须是灰度图像.因此,在通常情况下,都要预先对图像进行阈值分割或者边缘检测处理,得到满意的二值图像后再将其作为参数使用.

2> 在Opencv中,都是从黑色背景中查找白色对象.因此,对象必须是白色,背景必须是黑色的.


绘制图像轮廓:
drawContours()函数
image = cv.drawContours(image,contours,contourIdx,color,thickness,lineType,hierarchy,maxLevel,offset)

"""
img = cv.imread("contours.bmp",cv.IMREAD_COLOR)[:320,:390]  # 将干扰选项截出去.
print(img.shape)
cv.imshow("Original",img)

gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
T,thres = cv.threshold(gray,127,255,cv.THRESH_BINARY)
T1,thresOtsu = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
image,contours,hierarchy = cv.findContours(thres,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
imageOtsu,contoursOtsu,hierarchyOtsu = cv.findContours(thresOtsu,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
print("T = {},T1 = {}".format(T,T1))

imgNew = img.copy()
imgOtsu = img.copy()
cv.drawContours(imgNew,contours,-1,(0,0,255),3)
cv.drawContours(imgOtsu,contoursOtsu,-1,(0,255,0),3)
cv.imshow("imgNew",imgNew)
cv.imshow("imgOtsu",imgOtsu)
cv.waitKey(0)
cv.destroyAllWindows()




















